home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / connx-1.0 / server.c < prev    next >
C/C++ Source or Header  |  1995-06-25  |  17KB  |  686 lines

  1. /*
  2.  * server for connx
  3.  */
  4. #include <sys/signal.h>
  5. #include "connect.h"
  6. #include "commun.h"
  7. #include <stdio.h>
  8. #include <sys/types.h>
  9. #include <sys/time.h>
  10. #define TRUE 1
  11. #define FALSE 0
  12.  
  13. #ifdef AIX
  14. #include <sys/select.h>
  15. #endif
  16. #define BUF_SIZ 255
  17. /* program argument list */
  18. #define NUM_FLAGS 5
  19. enum
  20.   {
  21.     F_ROWS, F_COLS, F_CONN, F_GAME, F_TIMEOUT
  22.   };
  23. int flags_val[] =
  24. {F_ROWS, F_COLS, F_CONN, F_GAME, F_TIMEOUT};
  25. char *flags_txt[] =
  26. {"-rows", "-cols", "-conn", "-gravity", "-timeout"};
  27.  
  28. /*globals */
  29. int sock;
  30. msg_conn connections;
  31. game_start game_attr;
  32.  
  33. /* prototypes */
  34. void usage (char *prog);
  35. int parse_args (int argc, char **argv, int *num_rows,
  36.         int *num_columns, int *num_to_connect,
  37.         int *game_type, int *timeout);
  38. int to_flag (char *string);
  39. void play_game ();
  40. void let_connect ();
  41. void compress_conn ();
  42. void print_choices_before_game ();
  43. void print_choices_during_game ();
  44. int handle_choices_before_game ();
  45. int handle_choices_during_game ();
  46. void server_exit ();
  47.  
  48. /*****************************************************************************/
  49.  
  50. main (int argc, char **argv)
  51.  
  52. {
  53.   int i, j;
  54.   int rc;
  55.  
  56.   /* set defaults */
  57.   game_attr.num_rows = DEF_ROW;
  58.   game_attr.num_columns = DEF_COL;
  59.   game_attr.num_connect = DEF_CONNECT;
  60.   game_attr.game_type = DEF_GAME;
  61.   game_attr.timeout = DEF_TIMEOUT;
  62.  
  63.   /* read from command line */
  64.   if (parse_args (argc, argv, &game_attr.num_rows, &game_attr.num_columns,
  65.           &game_attr.num_connect, &game_attr.game_type,
  66.           &game_attr.timeout) == -1)
  67.     {
  68.       usage (argv[0]);
  69.       exit (1);
  70.     }
  71.  
  72.  
  73.   /* clean up nicely on kill */
  74.   signal (SIGINT, server_exit);
  75.  
  76.   rc = server_open_socket (&sock);
  77.   if (rc != 0)
  78.     {
  79.       perror ("cannot open socket\n");
  80.       exit (1);
  81.     }
  82.  
  83.   connections.number_of_conn = 0;
  84.   while (1)
  85.     {
  86.       print_choices_before_game ();
  87.       printf ("Choice: ");
  88.       fflush (stdout);
  89.       let_connect ();
  90.       print_choices_during_game ();
  91.       printf ("Choice: ");
  92.       fflush (stdout);
  93.       play_game ();
  94.     }
  95. }
  96.  
  97. /*****************************************************************************/
  98. /*internals*******************************************************************/
  99. /*****************************************************************************/
  100.  
  101. void
  102. print_choices_before_game ()
  103. {
  104.   printf ("\n");
  105.   printf ("************************************************************\n");
  106.   printf ("*                   Welcome to connX                       *\n");
  107.   printf ("* Choices:                                                 *\n");
  108.   printf ("*                                                          *\n");
  109.   printf ("* h: print this menu                                       *\n");
  110.   printf ("* l: list players connected                                *\n");
  111.   printf ("* k: kill a player                                         *\n");
  112.   printf ("* s: start the game                                        *\n");
  113.   printf ("* c: change game attributes                                *\n");
  114.   printf ("* a: list the game attributes                              *\n");
  115.   printf ("* t: assign players to a team                              *\n");
  116.   printf ("* w: swap position of 2 players                            *\n");
  117.   printf ("* x: exit the program                                      *\n");
  118.   printf ("************************************************************\n");
  119.   printf ("\n\n");
  120. }
  121.  
  122. /*****************************************************************************/
  123.  
  124. int
  125. handle_choices_before_game ()
  126. {
  127.   char ret, c, buf[BUF_SIZ];
  128.   int pn, pn2, tn, temp, i, rc;
  129.   char temp_name[NAME_SIZE];
  130.  
  131.   bzero (buf, BUF_SIZ);
  132.   scanf ("%[^\n]", buf);
  133.   scanf ("%c", &ret);
  134.   c = buf[0];
  135.   switch (c)
  136.     {
  137.     case 'h':
  138.       print_choices_before_game ();
  139.       break;
  140.     case 'l':
  141.       compress_conn ();
  142.       if (connections.number_of_conn == 0)
  143.     printf ("No connections\n");
  144.       else
  145.     for (i = 0; i < connections.number_of_conn; i++)
  146.       printf ("Player %d: %s: team: %d\n", i + 1, game_attr.players[i],
  147.           game_attr.team_numbers[i]);
  148.       break;
  149.     case 'k':
  150.       printf ("Player number[1-%d]: ", connections.number_of_conn);
  151.       rc = scanf ("%[^\n]", buf);
  152.       scanf ("%c", &ret);
  153.       if (rc != 0)
  154.     {
  155.       sscanf (buf, "%d", &pn);
  156.       if (pn >= 0 && pn <= connections.number_of_conn)
  157.         {
  158.           close_socket (&connections.conns[pn - 1]);
  159.           compress_conn ();
  160.         }
  161.     }
  162.       break;
  163.     case 's':
  164.       return 1;
  165.       break;
  166.     case 'c':
  167.       printf ("Number of rows[%d]: ", game_attr.num_rows);
  168.       rc = scanf ("%[^\n]", buf);
  169.       scanf ("%c", &ret);
  170.       if (rc != 0)
  171.     {
  172.       sscanf (buf, "%d", &temp);
  173.       if (temp > 0 && temp <= MAX_ROW)
  174.         game_attr.num_rows = temp;
  175.     }
  176.       printf ("Number of columns[%d]: ", game_attr.num_columns);
  177.       rc = scanf ("%[^\n]", buf);
  178.       scanf ("%c", &ret);
  179.       if (rc != 0)
  180.     {
  181.       sscanf (buf, "%d", &temp);
  182.       if (temp > 0 && temp <= MAX_COL)
  183.         game_attr.num_columns = temp;
  184.     }
  185.       printf ("Number to connect[%d]: ", game_attr.num_connect);
  186.       rc = scanf ("%[^\n]", buf);
  187.       scanf ("%c", &ret);
  188.       if (rc != 0)
  189.     {
  190.       sscanf (buf, "%d", &temp);
  191.       if (temp > 0 && temp <= MAX_CONNECT)
  192.         game_attr.num_connect = temp;
  193.     }
  194.       printf ("Game type (%d=gravity %d=nogravity) [%d]: ", GRAVITY, NOGRAVITY,
  195.           game_attr.game_type);
  196.       rc = scanf ("%[^\n]", buf);
  197.       scanf ("%c", &ret);
  198.       if (rc != 0)
  199.     {
  200.       sscanf (buf, "%d", &temp);
  201.       if (temp == GRAVITY || temp == NOGRAVITY)
  202.         game_attr.game_type = temp;
  203.     }
  204.       printf ("Timeout[%d]: ", game_attr.timeout);
  205.       rc = scanf ("%[^\n]", buf);
  206.       scanf ("%c", &ret);
  207.       if (rc != 0)
  208.     {
  209.       sscanf (buf, "%d", &temp);
  210.       if (temp >= 0)
  211.         game_attr.timeout = temp;
  212.     }
  213.       break;
  214.     case 'a':
  215.       printf ("Number of rows: %d\n", game_attr.num_rows);
  216.       printf ("Number of columns: %d\n", game_attr.num_columns);
  217.       printf ("Number to connect: %d\n", game_attr.num_connect);
  218.       printf ("Game type (%d=gravity %d=nogravity): %d\n",
  219.           GRAVITY, NOGRAVITY, game_attr.game_type);
  220.       printf ("Timeout: %d\n", game_attr.timeout);
  221.       break;
  222.     case 't':
  223.       printf ("Player number[1-%d]: ", connections.number_of_conn);
  224.       rc = scanf ("%[^\n]", buf);
  225.       scanf ("%c", &ret);
  226.       if (rc != 0)
  227.     {
  228.       sscanf (buf, "%d", &pn);
  229.       printf ("Team number[1-%d]: ", connections.number_of_conn);
  230.       rc = scanf ("%[^\n]", buf);
  231.       scanf ("%c", &ret);
  232.       if (rc != 0)
  233.         {
  234.           sscanf (buf, "%d", &tn);
  235.           if (pn >= 1 && tn >= 1 && pn <= connections.number_of_conn
  236.           && tn <= connections.number_of_conn)
  237.         game_attr.team_numbers[pn - 1] = tn;
  238.         }
  239.     }
  240.       break;
  241.     case 'w':
  242.       printf ("First player[1-%d]: ", connections.number_of_conn);
  243.       rc = scanf ("%[^\n]", buf);
  244.       scanf ("%c", &ret);
  245.       if (rc != 0)
  246.     {
  247.       sscanf (buf, "%d", &pn);
  248.       printf ("Second player[1-%d]: ", connections.number_of_conn);
  249.       rc = scanf ("%[^\n]", buf);
  250.       scanf ("%c", &ret);
  251.       if (rc != 0)
  252.         {
  253.           sscanf (buf, "%d", &pn2);
  254.           if (pn >= 1 && pn2 >= 1 && pn <= connections.number_of_conn &&
  255.           pn2 <= connections.number_of_conn)
  256.         {
  257.           temp = game_attr.team_numbers[pn - 1];
  258.           game_attr.team_numbers[pn - 1] = game_attr.team_numbers[pn2 - 1];
  259.           game_attr.team_numbers[pn2 - 1] = temp;
  260.           temp = connections.conns[pn - 1];
  261.           connections.conns[pn - 1] = connections.conns[pn2 - 1];
  262.           connections.conns[pn2 - 1] = temp;
  263.           strcpy (temp_name, game_attr.players[pn - 1]);
  264.           strcpy (game_attr.players[pn - 1], game_attr.players[pn2 - 1]);
  265.           strcpy (game_attr.players[pn2 - 1], temp_name);
  266.         }
  267.         }
  268.     }
  269.       break;
  270.     case 'x':
  271.       return -1;
  272.       break;
  273.     default:
  274.       print_choices_before_game();
  275.       break;
  276.     }
  277.   printf ("Choice: ");
  278.   fflush (stdout);
  279.   return 0;
  280. }
  281.  
  282.  
  283. /*****************************************************************************/
  284.  
  285. void
  286. print_choices_during_game ()
  287. {
  288.   printf ("\n");
  289.   printf ("************************************************************\n");
  290.   printf ("*                  Game In Progress                        *\n");
  291.   printf ("* Choices:                                                 *\n");
  292.   printf ("*                                                          *\n");
  293.   printf ("* h: print this menu                                       *\n");
  294.   printf ("* x: stop the game                                         *\n");
  295.   printf ("************************************************************\n");
  296.   printf ("\n\n");
  297. }
  298.  
  299. /*****************************************************************************/
  300.  
  301. int
  302. handle_choices_during_game ()
  303. {
  304.   char ret, c, buf[BUF_SIZ];
  305.   int rc = 0;
  306.  
  307.   bzero (buf, BUF_SIZ);
  308.   scanf ("%[^\n]", buf);
  309.   scanf ("%c", &ret);
  310.   c = buf[0];
  311.  
  312.   switch (c)
  313.     {
  314.     case 'h':
  315.       print_choices_during_game ();
  316.       break;
  317.     case 'x':
  318.       rc = -1;
  319.       break;
  320.     default:
  321.       print_choices_during_game();
  322.       break;
  323.     }
  324.  
  325.   printf ("Choice: ");
  326.   fflush (stdout);
  327.   return rc;
  328. }
  329.  
  330. /****************************************************************************/
  331.  
  332.  
  333. /*
  334.  * get rid of any closed connections and compress player list
  335.  */
  336. void
  337. compress_conn ()
  338. {
  339.   int i, j, used, team;
  340.   for (i = 0; i < connections.number_of_conn; i++)
  341.     if (check_status (&connections.conns[i]) == -1)
  342.       {
  343.     team = game_attr.team_numbers[i];
  344.     for (j = i; j < connections.number_of_conn - 1; j++)
  345.       {
  346.         connections.conns[j] = connections.conns[j + 1];
  347.         strcpy (game_attr.players[j], game_attr.players[j + 1]);
  348.         game_attr.team_numbers[j] = game_attr.team_numbers[j + 1];
  349.       }
  350.     connections.number_of_conn--;
  351.  
  352.     /* check if anyone else is using the team number */
  353.     used = 0;
  354.     for (j = 0; j < connections.number_of_conn; j++)
  355.       if (game_attr.team_numbers[j] == team)
  356.         used = 1;
  357.  
  358.     /* if no one is using it, compress team numbers */
  359.     if (used == 0)
  360.       for (j = 0; j < connections.number_of_conn; j++)
  361.         if (game_attr.team_numbers[j] > team)
  362.           game_attr.team_numbers[j]--;
  363.  
  364.     /* check the connection i has been replaced with */
  365.     i--;
  366.       }
  367. }
  368.  
  369. /*****************************************************************************/
  370.  
  371. void
  372. let_connect ()
  373. {
  374.   char pick;
  375.   int rc, i, num;
  376.   gen_msg msg_recv;
  377.   char recv_arr[512];
  378.   new_player *add_player_msg;
  379.   struct fd_set readfs;
  380.   int used, unused;
  381.  
  382.   compress_conn ();
  383.   msg_recv.msg = (char *) recv_arr;
  384.   /* let the players connect */
  385.   while (1)
  386.     {
  387.       FD_ZERO (&readfs);
  388.       FD_SET (0, &readfs);    /*stdin*/
  389.       FD_SET (sock, &readfs);
  390.  
  391.       if ((num = select (sock + 1, &readfs, NULL, NULL, NULL)) < 0)
  392.     {
  393.       printf ("select error\n");
  394.       exit (1);
  395.     }
  396.       if (FD_ISSET (sock, &readfs))
  397.  
  398.     {            /* new players connects */
  399.       compress_conn ();
  400.       rc = server_accept_connection (sock, &connections);
  401.       if (rc != -1)
  402.         {
  403.           rc = read_message (&connections.conns[connections.
  404.                             number_of_conn - 1],
  405.                  &msg_recv);
  406.           if (rc == -1 || msg_recv.msg_type != NEW_PLAYER)
  407.         {
  408.           close_socket
  409.             (&connections.conns[connections.number_of_conn]);
  410.           connections.number_of_conn--;
  411.         }
  412.           else
  413.         {
  414.           add_player_msg = (new_player *) msg_recv.msg;
  415.           strcpy (game_attr.players[connections.number_of_conn - 1],
  416.               add_player_msg->name);
  417.  
  418.           /* find unused team number */
  419.           unused = 0;
  420.           used = 1;
  421.           while (used == 1)
  422.             {
  423.               unused++;
  424.               used = 0;
  425.               for (i = 0; i < (connections.number_of_conn - 1); i++)
  426.             if (game_attr.team_numbers[i] == unused)
  427.               used = 1;
  428.             }
  429.  
  430.           game_attr.team_numbers[connections.number_of_conn - 1]
  431.             = unused;
  432.           printf ("\nplayer %s added.\n", add_player_msg->name);
  433.           printf ("Choice: ");
  434.           fflush (stdout);
  435.         }
  436.         }
  437.     }
  438.  
  439.       if (FD_ISSET (0, &readfs))
  440.     {            /* request from stdin */
  441.       rc = handle_choices_before_game ();
  442.       if (rc == 1)
  443.         break;        /* start game */
  444.       else if (rc == -1)
  445.         server_exit ();
  446.     }
  447.     }
  448.  
  449.   compress_conn ();
  450. }
  451.  
  452. /*****************************************************************************/
  453.  
  454. void
  455. play_game ()
  456. {
  457.   int i, j;
  458.   int rc;
  459.  
  460.   game_end game_end;
  461.   gen_msg msg_recv;
  462.   char recv_arr[MAX_DATA];
  463.   int game_over = FALSE;
  464.   int got_move;
  465.   my_move *move;
  466.   others_move others_move;
  467.   int still_out_there;
  468.   int num_players;
  469.   whose_move whose;
  470.   struct fd_set readfs;
  471.  
  472.   msg_recv.msg = (char *) recv_arr;
  473.   num_players = connections.number_of_conn;
  474.   game_attr.num_players = num_players;
  475.   if (connections.number_of_conn == 0)
  476.     {
  477.       printf ("No players\n");
  478.       return;
  479.     }
  480.  
  481.   allocate (game_attr.game_type, game_attr.num_rows, game_attr.num_columns,
  482.         num_players, game_attr.num_connect);
  483.  
  484.   /* tell players game is to start */
  485.   for (i = 0; i < num_players; i++)
  486.     {
  487.       game_attr.your_number = i + 1;
  488.       rc = send_message (&connections.conns[i], GAME_START,
  489.              sizeof (game_attr), (char *) &game_attr);
  490.     }
  491.   /*play the game*/
  492.   while (game_over == FALSE)
  493.     {
  494.       still_out_there = 0;
  495.       for (i = 0; i < connections.number_of_conn; i++)
  496.     {
  497.  
  498.       /* alert person whose turn it is */
  499.       rc = send_message (&connections.conns[i], YOUR_MOVE,
  500.                  0, (char *) NULL);
  501.       if (rc != -1)
  502.         {
  503.           still_out_there = 1;
  504.  
  505.           /* tell everyone whose move it is*/
  506.           whose.player = i + 1;
  507.           for (j = 0; j < connections.number_of_conn; j++)
  508.         if (j != i)
  509.           send_message (&connections.conns[j], WHOSE_MOVE,
  510.                 sizeof (whose_move), (char *) &whose);
  511.  
  512.           /* get move and handle stdin*/
  513.           got_move = FALSE;
  514.           while (got_move == FALSE)
  515.         {
  516.           FD_ZERO (&readfs);
  517.           FD_SET (0, &readfs);    /*stdin*/
  518.           FD_SET (connections.conns[i], &readfs);
  519.           select (connections.conns[i] + 1, &readfs, NULL, NULL, NULL);
  520.  
  521.           if (FD_ISSET (connections.conns[i], &readfs))
  522.             got_move = TRUE;
  523.           if (FD_ISSET (0, &readfs))
  524.             if (handle_choices_during_game () == -1)
  525.               {
  526.             game_end.winner = CANCEL_GAME;
  527.             game_over = TRUE;
  528.             /* tell client to abandon his move */
  529.             send_message (&connections.conns[i], CANCEL_MOVE, 0, NULL);
  530.               }
  531.         }
  532.  
  533.           rc = read_message (&connections.conns[i], &msg_recv);
  534.           if (rc != -1 && msg_recv.msg_type == MY_MOVE)
  535.         {
  536.           move = (my_move *) msg_recv.msg;
  537.           if (move->move.row != FORFEIT ||
  538.               move->move.column != FORFEIT)
  539.             {
  540.               move->rc = add_to_board (&(move->move),
  541.                            game_attr.team_numbers[i]);
  542.               rc = send_message (&connections.conns[i], MY_MOVE,
  543.                      sizeof (my_move), (char *) move);
  544.               if (move->rc == -1 && rc == 0)
  545.             i--;
  546.             }
  547.           else
  548.             move->rc = -1;
  549.         }
  550.           else
  551.         close_socket (&connections.conns[i]);
  552.  
  553.           if (rc == 0 && move->rc == 0)
  554.         {
  555.  
  556.           /* tell everyone the move*/
  557.           others_move.player_number = i + 1;
  558.           others_move.move = move->move;
  559.           for (j = 0; j < connections.number_of_conn; j++)
  560.             send_message (&connections.conns[j],
  561.                   OTHERS_MOVE, sizeof (others_move),
  562.                   (char *) &others_move);
  563.  
  564.           rc = check_for_win (move->move, &game_end.connect[0],
  565.                       &game_end.connect[1]);
  566.           if (rc == 0)
  567.             {
  568.               game_over = TRUE;
  569.               game_end.winner = i + 1;
  570.             }
  571.  
  572.           rc = check_for_tie ();
  573.           if (rc == 0)
  574.             {
  575.               game_over = TRUE;
  576.               game_end.winner = TIE_GAME;
  577.             }
  578.  
  579.         }
  580.           if (game_over == TRUE)
  581.         break;
  582.         }
  583.     }
  584.       if (still_out_there == 0)
  585.     {
  586.       /* No one left in the game */
  587.       return;
  588.     }
  589.     }
  590.  
  591.   /* tell everyone game is over */
  592.   for (j = 0; j < connections.number_of_conn; j++)
  593.     send_message (&connections.conns[j], GAME_END, sizeof (game_end),
  594.           (char *) &game_end);
  595. }
  596.  
  597. /***************************************************************************/
  598.  
  599.  
  600. /*
  601.  * command line processing
  602.  */
  603. int
  604. parse_args (int argc, char **argv, int *num_rows,
  605.         int *num_columns, int *num_to_connect,
  606.         int *game_type, int *timeout)
  607. {
  608.   int i;
  609.   int flag;
  610.  
  611.   if (((argc - 1) % 2) != 0)
  612.     return -1;
  613.   for (i = 1; i < argc; i = i + 2)
  614.     {
  615.       flag = to_flag (argv[i]);
  616.       switch (flag)
  617.     {
  618.     case F_ROWS:
  619.       *num_rows = atoi (argv[i + 1]);
  620.       break;
  621.     case F_COLS:
  622.       *num_columns = atoi (argv[i + 1]);
  623.       break;
  624.     case F_CONN:
  625.       *num_to_connect = atoi (argv[i + 1]);
  626.       break;
  627.     case F_GAME:
  628.       if (strcmp (argv[i + 1], "yes") == 0)
  629.         *game_type = GRAVITY;
  630.       else if (strcmp (argv[i + 1], "no") == 0)
  631.         *game_type = NOGRAVITY;
  632.       else
  633.         return -1;
  634.       break;
  635.     case F_TIMEOUT:
  636.       *timeout = atoi (argv[i + 1]);
  637.       break;
  638.     default:
  639.       return -1;
  640.       break;
  641.     }
  642.     }
  643.   return 0;
  644. }
  645.  
  646. /*****************************************************************************/
  647.  
  648. int
  649. to_flag (char *string)
  650. {
  651.   int i;
  652.  
  653.   for (i = 0; i < NUM_FLAGS; i++)
  654.     if (strcmp (string, flags_txt[i]) == 0)
  655.       return flags_val[i];
  656.   return -1;
  657. }
  658.  
  659. /*****************************************************************************/
  660.  
  661. void
  662. usage (char *prog)
  663. {
  664.   int i;
  665.  
  666.   printf ("Usage: %s \n", prog);
  667.   printf ("-rows <num_rows>\n");
  668.   printf ("-cols <num_cols>\n");
  669.   printf ("-conn <num_to_connect>\n");
  670.   printf ("-gravity <yes or no>\n");
  671.   printf ("-timeout <num>\n\n");
  672. }
  673.  
  674. /*****************************************************************/
  675.  
  676. void
  677. server_exit ()
  678. {
  679.   int i;
  680.   for (i = 0; i < connections.number_of_conn; i++)
  681.     close_socket (&connections.conns[i]);
  682.   close_socket (&sock);
  683.   printf ("\n");
  684.   exit (0);
  685. }
  686.